package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"
	"time"
)

var appDataPath string

func main() {
	//这里是日志的有关操作
	InitAppDataPath()
	var logFile *os.File
	relog := func(time time.Time) {
		log.SetOutput(os.Stdout)
		tag := "ssk"
		//if 0 != *ginPort {
		//	tag += "-" + xutil.ToString(*ginPort)
		//}
		if logFile != nil {
			log.Println("日志logFile != nil")
			_ = logFile.Close()
			renameErr := os.Rename(logFile.Name(), strings.ReplaceAll(logFile.Name(), ".txt", "   "+time.Format("02 15.04.05")+".txt"))
			if renameErr != nil {
				log.Println("日志重命名os.Rename错误：", renameErr, "路径是：", logFile)
			} else {
				log.Println("日志重命名成功:", logFile)
			}
			logFile = nil
		}
		
		var err error
		logPath := filepath.Join(appDataPath, "log-"+tag+"-"+time.Format("2006-01-02")+".txt")
		logFile, err = os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		log.Println("日志路径为:", logPath)
		if err == nil {
			log.SetOutput(io.MultiWriter(logFile, os.Stdout))
			RedirectStderr(logFile)
		}
	}
	
	log.SetPrefix("\r\n")
	log.SetFlags(log.Lmicroseconds)
	now := time.Now()
	relog(now)
	log.Println("日志路径为123:", " C:\\Users\\0921ssk\\AppData\\Roaming\\LearnGoXsuperzone\\log-ssk-2024-05-31.txt")
	//定时器执行
	//timeTickerOne()
	
	logPrintlnTest()
	
	/*
		errorOne := os.Mkdir("AppDataPath", 0666)
		if errorOne != nil {
			fmt.Println(errorOne)
			//return
		}
	
		var logFile *os.File
		relog := func(time time.Time) {
			log.SetOutput(os.Stdout)
			tag := "LearnGo.App" + "1.0.0"
			if logFile != nil {
				_ = logFile.Close()
				_ = os.Rename(logFile.Name(), strings.ReplaceAll(logFile.Name(), ".txt", "   "+time.Format("02 15.04.05")+".txt"))
				logFile = nil
			}
			var err error //2006-01-02
			logFile, err = os.OpenFile(filepath.Join("AppDataPath", "log-"+tag+"-"+time.Format("02 15.04.05")+".txt"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
			if err == nil {
	
				log.SetOutput(io.MultiWriter(logFile, os.Stdout))
				RedirectStderr(logFile)
			}
			fmt.Println(err)
		}
	*/
	
	/*
		logFile, err := os.OpenFile("./goProject.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
		if err != nil {
			fmt.Println("open log file failed, err:", err)
			return
		}
	*/
	
	/*
		log.Println("这是一条很普通的日志。")
		log.Println("这是一条很普通的日志2。")
		//log.SetOutput(logFile)
		log.SetPrefix("\r\n")
		log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)
	
		now := time.Now()
		relog(now)
		//log.Infoln("接口请求成功与否code码:")
		log.Println("这是一条很普通的日志。")
		log.Println("这是一条很普通的日志2。")
	*/
	
	//socket.NTCPClient()
	//socket.NUDPClient()
	//socket.NUnixClient()
	/*
			app := &cli.App{
				Name:  "greet",
				Usage: "fight the loneliness!",
				Action: func(*cli.Context) error {
					Println("Hello friend!")
					//fmt.Println("Hello friend!")
					return nil
				},
			}
	
			app.Flags = []cli.Flag{
	
				cli.StringFlag{
					Name: "config",
					Usage: `Input config file path.File format:
		{
			"click":{
				"rules":[
					{
						"title":"window title1",
						"matchType":"stitle",//This value can be stitle(start with),ititle(include) and title(full title)
						"button":"ok"//This  value should specify the control ID of the button, or one of the following predefined buttons: yes, no, ok, cancel, retry, ignore, close, help.
					},
					{
						"title":"window title2",
						"matchType":"title",
						"button":"0x00001234"
					}
				]
			}
		}
		`,
					Required: true,
					//Destination: "c/config.ConfigFilePath",
				},
				cli.BoolFlag{
					Name:  "click",
					Usage: "Auto click buttons in configuration path.",
					//Destination: "d/config.Click",
				},
				cli.BoolFlag{
					Name:  "auto",
					Usage: "Auto reload config file.",
					//Destination: "e/config.AutoLoadConfig",
				},
				cli.StringFlag{
					Name:     "auto-path",
					Usage:    "Auto reload notify path",
					Required: true,
					//Destination: "f/config.AutoLoadNotifyPath",
				},
				cli.StringFlag{
					Name:  "agent-root",
					Value: "C:/software",
					Usage: "Agent root path.It includes agent,process-controller and other input/output/config files.",
					//Destination: "g/config.XneoAgentPath",
				},
				cli.IntFlag{
					Name:  "memory-limit",
					Value: 0,
					Usage: "Monitor memory limit.",
					//Destination: "h:config.MemoryULimit",
				},
			}
	
			if err := app.Run(os.Args); err != nil {
				log.Fatal(err)
			}
			(&cli.App{}).Run(os.Args)
			//app.Run(os.Args)
	*/
	
	/*
		app := &cli.App{
			Name:  "boom",
			Usage: "make an explosive entrance",
			Action: func(*cli.Context) error {
				fmt.Println("boom! I say!")
				return nil
			},
		}
	
		if err := app.Run(os.Args); err != nil {
			log.Fatal(err)
		}
	*/
	
	//(&cli.App{}).Run(os.Args)
	
	/*
		var language string
		//fmt.Println("123")
		app := &cli.App{
			Name:    "godaily day003",
			Version: "v13",
			Usage:   "godaily day003 test",
			Flags: []cli.Flag{ // 接受的 flag
				&cli.StringFlag{ // string
					Name: "lang", // flag 名称
					//Aliases:     []string{"l"}, // 别名
					Value:       "english", // 默认值
					Usage:       "language for the greeting",
					Destination: &language, // 指定地址，如果没有可以通过 *cli.Context 的 GetString 获取
					Required:    true,      // flag 必须设置
				},
			},
			Action: func(c *cli.Context) error {
				name := "who"
				if c.NArg() > 0 {
					name = c.Args().Get(0)
				}
				if language == "chinese" {
					fmt.Println("你好啊", name)
				} else {
					fmt.Println("Hello", name)
				}
				return nil
			},
		}
	
		if err := app.Run(os.Args); err != nil {
			log.Fatal(err)
		}
	*/
}

func logPrintlnTest() {
	name := "Alice"
	age := "30"
	//使用字符串格式化拼接
	log.Println("User info:", name, "is", age, "years old.")
	
	//或者直接使用+操作符拼接
	additionalInfo := "User is active."
	log.Println("User info: " + name + "is" + age + "years old. Additional info：" + additionalInfo + ".")
}

func timeTickerOne() {
	ticker := time.NewTicker(3 * time.Second)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			log.Println("Hello, world!")
			//fmt.Println("Hello, world!")
		}
	}
	
	//猜测下这里time.Sleep会有什么影响？
	//time.Sleep(time.Second * 4)
}

func InitAppDataPath() {
	cache := SysAppData()
	fmt.Println("SysAppData路径为：", cache) //输出结果为：SysAppData路径为： C:\Users\0921ssk\AppData\Roaming
	
	Product := "LearnGo"
	app := "xsuperzone"
	ProductApp := strings.Title(Product) + strings.Title(app)
	//productDir := filepath.Join(cache, strings.Title("LearnGo"))
	//AppDataEnv := strings.Join([]string{strings.ToUpper(Product), strings.ToUpper(app), "DATA"}, "_")
	appDataPath = filepath.Join(cache, ProductApp)
	_ = os.MkdirAll(appDataPath, os.ModePerm)
}

func IsWindows() bool {
	sys := runtime.GOOS
	return "windows" == sys
}

func IsExist(path string) bool {
	_, err := os.Stat(path)
	if err != nil {
		//log.Println("xutil.IsExist", err, "os.IsExist", os.IsExist(err))
	}
	return err == nil || os.IsExist(err)
}

func AppDirPath() string {
	dir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	//dir = strings.ReplaceAll(dir, "\\", "/")
	return dir
}

func SysAppData() (path string) {
	if IsWindows() {
		path = os.Getenv("AppData")
		if !IsExist(path) {
			path = AppDirPath()
		}
	} else {
		path = os.Getenv("HOME")
	}
	return
}

func RedirectStderr(f *os.File) {
	err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
	if err != nil {
		log.Println("Failed to redirect stderr to file:", err)
	}
	// SetStdHandle does not affect prior references to stderr
	os.Stderr = f
}

var (
	kernel32         = syscall.NewLazyDLL("kernel32.dll")
	procSetStdHandle = kernel32.NewProc("SetStdHandle")
)

func setStdHandle(stdhandle int32, handle syscall.Handle) error {
	r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
	if r0 == 0 {
		if e1 != 0 {
			return error(e1)
		}
		return syscall.EINVAL
	}
	return nil
}
